﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="TrickleToCollection.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
//   Trickles a source collection to the destination...
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WP7Contrib.Collections
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Threading;

    public abstract class BaseTrickleToCollection<T> : ITrickleToCollection<T>
    {
        public bool Pending { get { return this.SourceQueue.Count != 0; } }

        public Queue<T> Source { get { return this.SourceQueue; } }

        public bool IsTrickling { get { return this.DispatcherTimer.IsEnabled; } }

        protected Queue<T> SourceQueue = new Queue<T>();

        protected readonly Action AddedAction;
        protected readonly Action StartedAction;
        protected readonly Action StoppedAction;
        protected readonly Action SuspendedAction;
        protected readonly Action ResumedAction;
        protected readonly Action CompletedAction;

        protected DispatcherTimer DispatcherTimer;
        protected TimeSpan StartupDelay = TimeSpan.FromMilliseconds(150);
        
        protected TimeSpan Delay;

        protected IList<T> Destination;
        protected int Count;

        protected BaseTrickleToCollection(Action addedAction, Action completedAction)
            : this (addedAction, () => {}, () => {}, () => {}, () => {}, completedAction)
        {
        }

        protected BaseTrickleToCollection(Action addedAction, Action startedAction, Action stoppedAction, Action suspendedAction, Action resumedAction, Action completedAction)
        {
            this.AddedAction = addedAction;
            this.StartedAction = startedAction;
            this.StoppedAction = stoppedAction;
            this.SuspendedAction = suspendedAction;
            this.ResumedAction = resumedAction;
            this.CompletedAction = completedAction;
        }

        public void Start(int trickleDelay, IEnumerable<T> sourceCollection, IList<T> destinationCollection)
        {
            sourceCollection.ToList().ForEach(i => this.SourceQueue.Enqueue(i));

            if (this.DispatcherTimer.IsEnabled)
            {
                return;
            }

            this.Count = 0;
            this.Destination = destinationCollection;
            this.Delay = TimeSpan.FromMilliseconds(trickleDelay);

            this.DispatcherTimer.Start();
            this.StartedAction();
        }

        public void Stop()
        {
            if (!this.DispatcherTimer.IsEnabled)
            {
                return;
            }

            this.DispatcherTimer.Stop();
            this.Count = 0;
            this.SourceQueue.Clear();
            this.StoppedAction();
        }

        public void Suspend()
        {
            if (!this.DispatcherTimer.IsEnabled)
            {
                return;
            }

            this.DispatcherTimer.Stop();
            this.SuspendedAction();
        }

        public void Resume()
        {
            if (this.DispatcherTimer.IsEnabled)
            {
                return;
            }

            this.DispatcherTimer.Start();
            this.ResumedAction();
        }
    }
}